package com.seven.dlandemo.ui;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.seven.dlandemo.QGameRegistryListener;
import com.seven.dlandemo.R;
import com.seven.dlandemo.control.ClingPlayControl;
import com.seven.dlandemo.control.callBack.ControlCallback;
import com.seven.dlandemo.databinding.ActivityWirelessDisplayBinding;
import com.seven.dlandemo.entity.ClingDevice;
import com.seven.dlandemo.entity.Config;
import com.seven.dlandemo.entity.DLANPlayState;
import com.seven.dlandemo.entity.IDevice;
import com.seven.dlandemo.entity.IResponse;
import com.seven.dlandemo.entity.Intents;
import com.seven.dlandemo.listener.DeviceListChangedListener;
import com.seven.dlandemo.service.ClingUpnpService;
import com.seven.dlandemo.service.manager.ClingDeviceManager;
import com.seven.dlandemo.service.manager.ClingManager;
import com.seven.dlandemo.service.manager.DeviceManager;

import org.fourthline.cling.model.meta.Device;
import org.fourthline.cling.model.types.DeviceType;
import org.fourthline.cling.model.types.UDADeviceType;
import org.fourthline.cling.registry.Registry;

import java.util.Collection;

import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;

public class WirelessDisplayViewModel {
    private static final String TAG = MainActivity.myTAG + WirelessDisplayViewModel.class.getSimpleName();
    private static final String ACTION_ERROR = "error";
    private static final String DEVICE_NAME = "deviceName";

    public static final DeviceType DMR_DEVICE_TYPE = new UDADeviceType("MediaRenderer");

    private Context mContext;
    private ListView list;
    private String mVideoUrl;

    private ArrayAdapter<ClingDevice> mDevicesAdapter;
    private ActivityWirelessDisplayBinding mViewBinding;
    private TransportStateBroadcastReceiver mTransportStateBroadcastReceiver;
    private QGameRegistryListener registryListener = new QGameRegistryListener();
    private ClingPlayControl mClingPlayControl = new ClingPlayControl();

    public WirelessDisplayViewModel(Activity context, ActivityWirelessDisplayBinding viewBinding) {
        Log.i(TAG, "WirelessDisplayViewModel construct");
        mContext = context;
        mViewBinding = viewBinding;
        initView();
        initListener();
        bindService();
        registerReceivers();
    }

    public void setVideoUrl(String url) {
        mVideoUrl = url;
    }

    private void initView() {
        Log.i(TAG, "initView");
        mDevicesAdapter = new DeviceListAdapter(mContext);
        list = mViewBinding.list;
        list.setAdapter(mDevicesAdapter);
    }

    private void initListener() {
        Log.i(TAG, "initListener");
//        mSubscription = new
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(mContext, "click:" + position + "", Toast.LENGTH_SHORT).show();
                // 选择连接设备
                ClingDevice item = mDevicesAdapter.getItem(position);
                if (item == null) {
                    return;
                }
                ClingManager.getInstance().setSelectedDevice(item);
                Device device = item.getDevice();
                if (device == null) {
                    return;
                }
                String selectedDeviceName = String.format("已选中: %s", device.getDetails().getFriendlyName());
                mViewBinding.selectedDevice.setText(selectedDeviceName);
            }
        });
        registryListener.setOnDeviceListChangedListener(new DeviceListChangedListener() {
            @Override
            public void onDeviceAdded(final IDevice device) {
                Log.i(TAG, "onDeviceAdded");
                Observable.empty().observeOn(AndroidSchedulers.mainThread()).doOnCompleted(new Action0() {
                    @Override
                    public void call() {
                        Log.i(TAG, "onDeviceAdded call");
                        mDevicesAdapter.addAll((ClingDevice) device);
                    }
                });
            }

            @Override
            public void onDeviceRemoved(final IDevice device) {
                Log.i(TAG, "onDeviceRemoved");
                Observable.empty().observeOn(AndroidSchedulers.mainThread()).doOnCompleted(new Action0() {
                    @Override
                    public void call() {
                        Log.i(TAG, "onDeviceRemoved call");
                        mDevicesAdapter.remove((ClingDevice) device);
                    }
                });
            }
        });
        // todo seekar事件
    }

    private void bindService() {
        Log.i(TAG, "bindService");
        Intent intent = new Intent(mContext, ClingUpnpService.class);
        mContext.bindService(intent, mUpnpServiceConnection, Context.BIND_AUTO_CREATE);
    }

    protected void onDestroy() {
        Log.i(TAG, "onDestroy");
        mContext.unbindService(mUpnpServiceConnection);
        mContext.unregisterReceiver(mTransportStateBroadcastReceiver);

        ClingManager.getInstance().destroy();
        ClingDeviceManager.getInstance().destroy();
    }

    private void registerReceivers() {
        Log.i(TAG, "registerReceivers");
        // Register play status broadcast
        mTransportStateBroadcastReceiver = new TransportStateBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intents.ACTION_PLAYING);
        filter.addAction(Intents.ACTION_PAUSED_PLAYBACK);
        filter.addAction(Intents.ACTION_STOPPED);
        filter.addAction(Intents.ACTION_TRANSITIONING);
        mContext.registerReceiver(mTransportStateBroadcastReceiver, filter);
    }

    private ServiceConnection mUpnpServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.i(TAG, "onServiceConnected");
            ClingUpnpService.LocalBinder binder = (ClingUpnpService.LocalBinder) iBinder;
            ClingUpnpService upnpService = binder.getService();
            ClingManager clingManager = ClingManager.getInstance();
            clingManager.setUpnpService(upnpService);
            clingManager.setDeviceManager(new DeviceManager());
            if (clingManager.getRegistry() != null) {
                clingManager.getRegistry().addListener(registryListener);
            }
            //Search
            clingManager.searchDevices();
//            refreshDeviceList();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.i(TAG, "onServiceDisconnected");
            Registry registry = ClingManager.getInstance().getRegistry();
            if (registry != null) {
                registry.removeListener(registryListener);
                registry.removeAllRemoteDevices();
//                registry.removeAllLocalDevices();
            }
            ClingManager.getInstance().setUpnpService(null);
        }
    };

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.refresh_devices:
                Log.i(TAG, "onClick refresh");
                refreshDeviceList();
                break;
            case R.id.play:
                play();
                break;
            case R.id.pause:
                pause();
                break;
            case R.id.stop:
                stop();
                break;
        }
    }

    /**
     * 播放
     */
    private void play() {
        @DLANPlayState.DLANPlayStates int currentState = mClingPlayControl.getCurrentState();
        // 通过判断状态来判断重新播放还是继续播放
        if (currentState == DLANPlayState.STOP) {
            if (TextUtils.isEmpty(mVideoUrl)) {
                throw new IllegalArgumentException("play url is empty! invoke setVideoUrl() before play");
            }
            mClingPlayControl.playNew(mVideoUrl, new ControlCallback() {
                @Override
                public void success(IResponse response) {
                    Log.d(TAG, "play success");
//                    ClingUpnpServiceManager.getInstance().subscribeMediaRender();
//                    getPositionInfo();
                    ClingManager.getInstance().registerAVTransport(mContext);
                    ClingManager.getInstance().registerRenderingControl(mContext);
                }

                @Override
                public void fail(IResponse response) {
                    Log.e(TAG, "play fail");
                    sendMessage(ACTION_ERROR);
                }
            });
        } else {
            mClingPlayControl.play(new ControlCallback() {
                @Override
                public void success(IResponse response) {
                    Log.d(TAG, "play success");
                }

                @Override
                public void fail(IResponse response) {
                    Log.e(TAG, "play fail");
                    sendMessage(ACTION_ERROR);
                }
            });
        }
    }

    /**
     * 暂停
     */
    private void pause() {
        mClingPlayControl.pause(new ControlCallback() {
            @Override
            public void success(IResponse response) {
                Log.d(TAG, "pause success");
            }

            @Override
            public void fail(IResponse response) {
                Log.e(TAG, "pause fail");
            }
        });
    }

    /**
     * 停止
     */
    private void stop() {
        mClingPlayControl.stop(new ControlCallback() {
            @Override
            public void success(IResponse response) {
                Log.d(TAG, "stop success");
            }

            @Override
            public void fail(IResponse response) {
                Log.e(TAG, "stop fail");
            }
        });
    }

    /**
     * 刷新设备
     */
    private void refreshDeviceList() {
        Log.i(TAG, "refreshDeviceList");
        Toast.makeText(mContext, "正在刷新", Toast.LENGTH_SHORT).show();
        long startTime = System.currentTimeMillis();
        Collection<ClingDevice> devices = ClingManager.getInstance().getDmrDevices();
        Log.d(TAG, "coast : " + (System.currentTimeMillis() - startTime));
        if (devices != null) {
            ClingDeviceManager.getInstance().setClingDeviceList(devices);
            mDevicesAdapter.clear();
            mDevicesAdapter.addAll(devices);
            list.invalidateViews(); // 刷新
        }
    }

    private void handleBroadcast(final String action) {
        switch (action) {
            case Intents.ACTION_PLAYING:
                Log.i(TAG, "Execute PLAY_ACTION");
                Toast.makeText(mContext, "正在投放", Toast.LENGTH_SHORT).show();
                mClingPlayControl.setCurrentState(DLANPlayState.PLAY);

                break;
            case Intents.ACTION_PAUSED_PLAYBACK:
                Log.i(TAG, "Execute PAUSE_ACTION");
                Toast.makeText(mContext, "暂停播放", Toast.LENGTH_SHORT).show();
                mClingPlayControl.setCurrentState(DLANPlayState.PAUSE);

                break;
            case Intents.ACTION_STOPPED:
                Log.i(TAG, "Execute STOP_ACTION");
                Toast.makeText(mContext, "停止播放", Toast.LENGTH_SHORT).show();
                mClingPlayControl.setCurrentState(DLANPlayState.STOP);

                break;
            case Intents.ACTION_TRANSITIONING:
                Log.i(TAG, "Execute TRANSITIONING_ACTION");
                Toast.makeText(mContext, "正在连接", Toast.LENGTH_SHORT).show();
                break;
            case ACTION_ERROR:
                Log.e(TAG, "Execute ERROR_ACTION");
                Toast.makeText(mContext, "投放失败", Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private void sendMessage(final String action){
        Observable.empty().observeOn(AndroidSchedulers.mainThread()).doOnCompleted(new Action0() {
            @Override
            public void call() {
                handleBroadcast(action);
            }
        }).subscribe();
    }

    /**
     * 接收状态改变信息
     */
    private class TransportStateBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "Receive playback intent:" + action);
            if (TextUtils.isEmpty(action)) {
                return;
            }
            sendMessage(action);
        }
    }
}
